using System;
using System.Web.UI;
using System.IO;
using System.Text.RegularExpressions;
using anrControls.SyntaxColoring;
using System.Web.UI.WebControls;
using System.Web.Caching;
using System.Web.UI.HtmlControls;
using SharpPieces.Web;

namespace SharpPieces.DemoApp
{

    /// <summary>
    /// The Demo master page.
    /// </summary>
    public partial class Labs : MasterPage
    {

        // Fields

        internal static Regex codeFileRegex = new Regex("< *% *@ * *Page.*(CodeFile=\"(.*?)\"|CodeBehind=\"(.*?)\").*?% *>", RegexOptions.Compiled | RegexOptions.Singleline);
        internal static Regex descriptionRegex = new Regex("< *% *@ * *Page.*(Description=\"(.*?)\").*?% *>", RegexOptions.Compiled | RegexOptions.Singleline);
        internal static Regex titleRegex = new Regex("< *% *@ * *Page.*(Title=\"(.*?)\").*?% *>", RegexOptions.Compiled | RegexOptions.Singleline);


        // Methods

        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.Init"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param>
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            // add aspx tab
            string aspxUnchangedCode;
            this.AddCodePreview(this.Page.MapPath(this.Page.AppRelativeVirtualPath), out aspxUnchangedCode);

            // resolve description & title
            if (Demo.descriptionRegex.IsMatch(aspxUnchangedCode))
            {
                Match descriptionMatch = Demo.descriptionRegex.Match(aspxUnchangedCode);
                if (descriptionMatch.Groups[2].Success && !string.IsNullOrEmpty(descriptionMatch.Groups[2].Value))
                {
                    this.labelDescription.Text = descriptionMatch.Groups[2].Value;
                }
            }
            if (Demo.titleRegex.IsMatch(aspxUnchangedCode))
            {
                Match titleMatch = Demo.titleRegex.Match(aspxUnchangedCode);
                if (titleMatch.Groups[2].Success && !string.IsNullOrEmpty(titleMatch.Groups[2].Value))
                {
                    this.labelTitle.Text = titleMatch.Groups[2].Value;
                }
            }

            // add the code tab
            if (Demo.codeFileRegex.IsMatch(aspxUnchangedCode))
            {
                Match codeFileMatch = Demo.codeFileRegex.Match(aspxUnchangedCode);
                this.AddCodePreview(this.Page.MapPath(codeFileMatch.Groups[codeFileMatch.Groups[2].Success ? 2 : 3].Value));
            }
            //string codeFile = string.Format("{0}.cs", this.Page.MapPath(this.Page.AppRelativeVirtualPath));
            //if (File.Exists(codeFile))
            //{
            //    this.AddCodePreview(codeFile);
            //}
        }

        /// <summary>
        /// Handles the TreeNodeDataBound event of the treeSampleList control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Web.UI.WebControls.TreeNodeEventArgs"/> instance containing the event data.</param>
        protected void treeSampleList_TreeNodeDataBound(object sender, TreeNodeEventArgs e)
        {
            if (string.IsNullOrEmpty(e.Node.NavigateUrl))
            {
                e.Node.SelectAction = TreeNodeSelectAction.Expand;
            }
            if (e.Node.NavigateUrl == this.Request.RawUrl)
            {
                this.labelTitle.Text = this.treeSampleList.SelectedNode.Text;
            }
        }

        /// <summary>
        /// Adds a tab code preview; it should be called after Init.
        /// The tab name and title will be parsed from the file name.
        /// </summary>
        /// <param name="fileName">File name.</param>
        public void AddCodePreview(string fileName)
        {
            string unchangedCode;
            this.AddCodePreview(fileName, out unchangedCode);
        }

        /// <summary>
        /// Adds a tab code preview; it should be called after Init.
        /// The tab name and title will be parsed from the file name.
        /// </summary>
        /// <param name="fileName">File name.</param>
        /// <param name="unchangedCode">The unchanged file code.</param>
        public void AddCodePreview(string fileName, out string unchangedCode)
        {
            if (null == fileName)
            {
                throw new ArgumentNullException("fileName");
            }

            FileInfo file = new FileInfo(fileName);
            if (!file.Exists)
            {
                unchangedCode = null;
                return;
            }

            this.AddCodePreview(file.Name.Replace(".", string.Empty), file.Name, fileName, out unchangedCode);
        }

        /// <summary>
        /// Adds a tab code preview; it should be called after Init.
        /// </summary>
        /// <param name="tabName">Tab name.</param>
        /// <param name="tabTitle">Tab title.</param>
        /// <param name="fileName">File name.</param>
        public void AddCodePreview(string tabName, string tabTitle, string fileName)
        {
            string unchangedCode;
            this.AddCodePreview(tabName, tabTitle, fileName, out unchangedCode);
        }

        /// <summary>
        /// Adds a tab code preview; it should be called after Init.
        /// </summary>
        /// <param name="tabName">Tab name.</param>
        /// <param name="tabTitle">Tab title.</param>
        /// <param name="fileName">File name.</param>
        /// <param name="unchangedCode">The unchanged file code.</param>
        public void AddCodePreview(string tabName, string tabTitle, string fileName, out string unchangedCode)
        {
            if (null == tabName)
            {
                throw new ArgumentNullException("tabName");
            }

            tabName = tabName.Replace(" ", string.Empty);

            if (string.Empty == tabName)
            {
                throw new ArgumentException("Invalid tabName value.");
            }

            if (null != this.divTabContainer.FindControl(tabName))
            {
                throw new ArgumentException("The tab having the same name already exists.");
            }

            if (null == fileName)
            {
                throw new ArgumentNullException("fileName");
            }


            // resolve the code
            string highlightedCode;
            if (null == this.Cache[fileName])
            {
                FileInfo file = new FileInfo(fileName);
                if (!file.Exists)
                {
                    unchangedCode = null;
                    return;
                }

                // read and highlight the code
                switch (file.Extension.ToLower())
                {
                    case ".cs":
                        {
                            using (TextReader reader = File.OpenText(file.FullName))
                            {
                                unchangedCode = reader.ReadToEnd();
                                highlightedCode = CodeHighlighterFactory.GetHighlighter(CodeSyntax.CSharpNet).ColorCode(unchangedCode);
                            }
                            break;
                        }
                    case ".vb":
                        {
                            using (TextReader reader = File.OpenText(file.FullName))
                            {
                                unchangedCode = reader.ReadToEnd();
                                highlightedCode = CodeHighlighterFactory.GetHighlighter(CodeSyntax.VbNet).ColorCode(unchangedCode);
                            }
                            break;
                        }
                    case ".aspx":
                    case ".ascx":
                    case ".master":
                    case ".skin":
                        {
                            using (TextReader reader = File.OpenText(file.FullName))
                            {
                                unchangedCode = reader.ReadToEnd();
                                highlightedCode = CodeHighlighterFactory.GetHighlighter(CodeSyntax.Aspx).ColorCode(unchangedCode);
                            }
                            break;
                        }
                    case ".css":
                        {
                            using (TextReader reader = File.OpenText(file.FullName))
                            {
                                unchangedCode = reader.ReadToEnd();
                                highlightedCode = CodeHighlighterFactory.GetHighlighter(CodeSyntax.Css).ColorCode(unchangedCode);
                            }
                            break;
                        }
                    case ".html":
                    case ".htm":
                        {
                            using (TextReader reader = File.OpenText(file.FullName))
                            {
                                unchangedCode = reader.ReadToEnd();
                                highlightedCode = CodeHighlighterFactory.GetHighlighter(CodeSyntax.Html).ColorCode(unchangedCode);
                            }
                            break;
                        }
                    case ".sql":
                        {
                            using (TextReader reader = File.OpenText(file.FullName))
                            {
                                unchangedCode = reader.ReadToEnd();
                                highlightedCode = CodeHighlighterFactory.GetHighlighter(CodeSyntax.Sql).ColorCode(unchangedCode);
                            }
                            break;
                        }
                    case ".xml":
                    case ".ent":
                    case ".dtd":
                    case ".rdf":
                    case ".atom":
                    case ".owl":
                    case ".xhtml":
                    case ".xsd":
                    case ".xsl":
                    case ".fo":
                    case ".rng":
                    case ".sch":
                    case ".svg":
                    case ".rss":
                    case ".plist":
                    case ".sln":
                    case ".csproj":
                    case ".vbproj":
                        {
                            using (TextReader reader = File.OpenText(file.FullName))
                            {
                                unchangedCode = reader.ReadToEnd();
                                highlightedCode = CodeHighlighterFactory.GetHighlighter(CodeSyntax.Xml).ColorCode(unchangedCode);
                            }
                            break;
                        }
                    default:
                        {
                            // not supported
                            unchangedCode = null;
                            return;
                        }

                }

                // add highlighted code to cache
                this.Cache.Insert(file.FullName, new Pair<string>(unchangedCode, highlightedCode), new CacheDependency(file.FullName));
            }
            else
            {
                unchangedCode = ((Pair<string>)this.Cache[fileName]).First;
                highlightedCode = ((Pair<string>)this.Cache[fileName]).Second;
            }

            // add tab body
            HtmlGenericControl codeContainer = new HtmlGenericControl("div");
            codeContainer.ID = tabName;
            codeContainer.InnerHtml = highlightedCode;
            this.divTabContainer.Controls.Add(codeContainer);

            // add tab head
            HtmlGenericControl spanTab = new HtmlGenericControl("span");
            spanTab.InnerText = tabTitle;
            HtmlAnchor aTab = new HtmlAnchor();
            aTab.HRef = string.Format("#{0}", codeContainer.ClientID);
            aTab.Controls.Add(spanTab);
            HtmlGenericControl liTab = new HtmlGenericControl("li");
            liTab.Controls.Add(aTab);
            this.ulTabHeaderList.Controls.Add(liTab);
        }

        public bool ShowDemoRuntime
        {
            set { this.pnlDemoSrc.Visible = this.divDemoRuntime.Visible = value; }
        }

    }

}